package com.amumu.drama.common.modules.sumapay.service.impl;

import cn.hutool.json.JSONUtil;
import com.amumu.drama.common.exception.ApiException;
import com.amumu.drama.common.exception.Asserts;
import com.amumu.drama.common.modules.sumapay.config.SumaPayConfig;
import com.amumu.drama.common.modules.sumapay.config.SumapayStaticVar;
import com.amumu.drama.common.modules.sumapay.dto.req.WeChatRefundReq;
import com.amumu.drama.common.modules.sumapay.dto.req.WeChatSingleOrderQueryReq;
import com.amumu.drama.common.modules.sumapay.dto.req.WechatPayReq;
import com.amumu.drama.common.modules.sumapay.dto.resp.WeChatPaySuccessResp;
import com.amumu.drama.common.modules.sumapay.dto.resp.WeChatRefundResp;
import com.amumu.drama.common.modules.sumapay.dto.resp.WechatPayResp;
import com.amumu.drama.common.modules.sumapay.service.WechatPayService;
import com.amumu.drama.common.modules.sumapay.tools.MD5Tools;
import com.amumu.drama.common.utils.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.Objects;

/**
 * @author sunzhuang
 * @date 2024/6/6 10:52
 * @slogan 天下风云出我辈, 一入代码岁月催
 * @desc todo
 */
@Slf4j
@Service
public class WechatPayServiceImpl implements WechatPayService {

    @Autowired
    private SumaPayConfig sumaPayConfig;

    /**
     * 创建订单
     *
     * @param request
     */
    @Override
    public WechatPayResp createOrder(WechatPayReq request) {
        if (request == null) {
            Asserts.fail("丰付支付请求参数为空");
        }
        request.setMerchantCode(sumaPayConfig.getMerchantCode());
        request.setTotalBizType(sumaPayConfig.getTotalBizType());
        request.setEnvFlag(sumaPayConfig.getEnvFlag());
        request.setRePayTimeOut(sumaPayConfig.getRePayTimeOut());
        request.setNoticeUrl(sumaPayConfig.getNoticeUrl());
        request.setBackUrl(sumaPayConfig.getBackUrl());
        request.setTerminalIp(sumaPayConfig.getTerminalIp());
        request.setMerAcct(sumaPayConfig.getMerKey());
        request.setBizType(sumaPayConfig.getTotalBizType());
        //创建加密参数
        StringBuilder sb = new StringBuilder();
        sb.append(request.getRequestType());
        sb.append(request.getRequestId());
        sb.append(request.getMerchantCode());
        sb.append(request.getTotalBizType());
        sb.append(request.getTotalPrice());
        sb.append(request.getGoodsDesc());
        sb.append(request.getEnvFlag());
        sb.append(request.getRePayTimeOut());
        sb.append(request.getNoticeUrl());
        sb.append(request.getBackUrl());
        sb.append(request.getPassThrough());
        String signature = MD5Tools.Md5(sb.toString(), sumaPayConfig.getMerKey());
        request.setSignature(signature);
        Map<String, String> body = JSONUtil.parseObj(request).toBean(Map.class);
        try {
            String result = HttpUtils.doPostFormAndGBK(SumapayStaticVar.WECHAT_CREATE_ORDER_URL, body);
            WechatPayResp resp = JSONUtil.toBean(result, WechatPayResp.class);
            StringBuilder resultSb = new StringBuilder()
                    .append(resp.getRequestId())
                    .append(resp.getResult())
                    .append(resp.getPayUrl())
                    .append(resp.getMpAppId())
                    .append(resp.getMpPath())
                    .append(resp.getErrorMsg());
            String returnSignStr = resultSb.toString();
            String signature2 = MD5Tools.Md5(returnSignStr, sumaPayConfig.getMerKey());
            if (!Objects.equals(signature2, resp.getSignature())) {
                log.error("丰付支付返回结果验签失败, body:{}, result:{}", body, result);
                Asserts.fail("丰付支付返回结果验签失败");
            }
            return resp;
        } catch (Exception e) {
            log.error("丰付创建订单失败", e);
            throw new ApiException(e);
        }
    }

    /**
     * 单笔订单查询
     *
     * @param request
     */
    @Override
    public WeChatPaySuccessResp singleQuery(WeChatSingleOrderQueryReq request) {
        if (request == null) {
            Asserts.fail("丰付查询单笔订单请求参数为空");
        }
        request.setMerchantCode(sumaPayConfig.getMerchantCode());
        //创建加密参数
        StringBuilder sb = new StringBuilder();
        sb.append(request.getRequestId());
        sb.append(request.getMerchantCode());
        sb.append(request.getOriginalRequestId());
        String signature = MD5Tools.Md5(sb.toString(), sumaPayConfig.getMerKey());
        Map<String, String> body = JSONUtil.parseObj(request).toBean(Map.class);
        body.put("signature", signature);
        try {
            String result = HttpUtils.doPostFormAndGBK(SumapayStaticVar.WECHAT_SINGLE_QUERY_URL, body);
            if (StringUtils.isBlank(result)) {
                return null;
            }
            WeChatPaySuccessResp resp = JSONUtil.toBean(result, WeChatPaySuccessResp.class);
            StringBuilder resultSb = new StringBuilder()
                    .append(resp.getRequestId())
                    .append(resp.getResult())
                    .append(resp.getMerchantCode())
                    .append(resp.getOriginalRequestId())
                    .append(resp.getTradeId())
                    .append(resp.getTradeSum())
                    .append(resp.getStatus())
                    .append(resp.getRequestTime());
            String returnSignStr = resultSb.toString();
            String signature2 = MD5Tools.Md5(returnSignStr, sumaPayConfig.getMerKey());
            if (!Objects.equals(signature2, resp.getSignature())) {
                log.error("丰付查询单笔订单返回结果验签失败, body:{}, result:{}", body, result);
                Asserts.fail("丰付查询单笔订单返回结果验签失败");
            }
            return resp;
        } catch (Exception e) {
            log.error("丰付创建订单失败", e);
            throw new ApiException(e);
        }
    }

    /**
     * 退款
     *
     * @param request
     */
    @Override
    public WeChatRefundResp refund(WeChatRefundReq request) {
        if (request == null) {
            Asserts.fail("丰付退款请求参数为空");
        }
        //创建加密参数
        StringBuilder sb = new StringBuilder();
        sb.append(request.getRequestId());
        sb.append(request.getOriginalRequestId());
        sb.append(request.getTradeProcess());
        sb.append(request.getFund());
        sb.append(request.getNoticeUrl());
        sb.append(request.getRemark());
        String signature = MD5Tools.Md5(sb.toString(), sumaPayConfig.getMerKey());
        Map<String, String> body = JSONUtil.parseObj(request).toBean(Map.class);
        body.put("signature", signature);
        try {
            String result = HttpUtils.doPostFormAndGBK(SumapayStaticVar.WECHAT_REFUND_URL, body);
            WeChatRefundResp resp = JSONUtil.toBean(result, WeChatRefundResp.class);
            StringBuilder resultSb = new StringBuilder()
                    .append(resp.getRequestId())
                    .append(resp.getResult())
                    .append(resp.getRemark());
            String returnSignStr = resultSb.toString();
            String signature2 = MD5Tools.Md5(returnSignStr, sumaPayConfig.getMerKey());
            if (!Objects.equals(signature2, resp.getResultSignature())) {
                log.error("丰付退款返回结果验签失败, body:{}, result:{}", body, result);
                Asserts.fail("丰付退款返回结果验签失败");
            }
            return resp;
        } catch (Exception e) {
            log.error("丰付创建订单失败", e);
            throw new ApiException(e);
        }
    }
}
